package com.zd;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.*;
import org.apache.hadoop.io.IOUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

public class HdfsClientDemo {

    FileSystem fs = null;
    Configuration configuration = null;

    @Before
    public void init() throws URISyntaxException, IOException,
            InterruptedException {

        //1 获取Hadoop 集群的configuration对象
        configuration = new Configuration();

        // configuration.set("fs.defaultFS", "hdfs://hadoop102:8020");
        // configuration.set("dfs.replication", "2");
        //2 根据configuration获取Filesystem对象
        fs = FileSystem.get(new URI("hdfs://hadoop102:8020"), configuration, "root");
    }

    @After
    public void destory() throws IOException {

        //4 释放FileSystem对象（类似数据库连接）
        fs.close();
    }

    @Test
    public void testCopyFromLocalFile() throws IOException, InterruptedException, URISyntaxException {

        // 1 获取文件系统
        Configuration configuration = new Configuration();
        //configuration.set("dfs.replication", "2");
        FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:8020"), configuration, "root");

        // 2 上传文件  data/gsm.txt首先是本地路径不是hdfs路径，然后是相对路径 不是绝对路径
        // windows的绝对路径是 盘符开头 c:/a/b.txt Linux unix 都是 /开头
        fs.copyFromLocalFile(new Path("data/gsm.txt"), new Path("/gsm2.txt"));

        // 3 关闭资源
        fs.close();
        System.out.println("end");
    }

    @Test
    public void testCopyToLocalFile() throws IOException, InterruptedException, URISyntaxException {

        // 1 获取文件系统
        Configuration configuration = new Configuration();
        FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:8020"), configuration, "root");

        // 2 执行下载操作
        // boolean delSrc 指是否将原文件删除
        // Path src 指要下载的文件路径
        // Path dst 指将文件下载到的路径
        // boolean useRawLocalFileSystem 是否开启文件校验
        fs.copyToLocalFile(false, new Path("/gsm.txt"), new Path("data/gsm_copy.txt"), true);

        // 3 关闭资源
        fs.close();
    }


    @Test
    public void testDelete() throws IOException, InterruptedException, URISyntaxException {

        // 1 获取文件系统
        Configuration configuration = new Configuration();
        FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:8020"), configuration, "root");

        // 2 执行删除
        fs.delete(new Path("/api_test/"), true);

        // 3 关闭资源
        fs.close();
    }


    @Test
    public void testListFiles() throws IOException, InterruptedException, URISyntaxException {

        // 1获取文件系统
        Configuration configuration = new Configuration();
        FileSystem fs = FileSystem.get(new URI("hdfs://mycluster"), configuration, "root");

        // 2 获取文件详情
        RemoteIterator<LocatedFileStatus> listFiles = fs.listFiles(new Path("/"), true);

        while (listFiles.hasNext()) {
            LocatedFileStatus status = listFiles.next();

            // 输出详情
            // 文件名称
            System.out.println(status.getPath().getName());

            // 长度
            System.out.println(status.getLen());


            // 权限
            System.out.println(status.getPermission());

            // 分组
            System.out.println(status.getGroup());

            // 获取存储的块信息
            BlockLocation[] blockLocations = status.getBlockLocations();
            for (BlockLocation blockLocation : blockLocations) {


                // 获取块存储的主机节点
                String[] hosts = blockLocation.getHosts();
                for (String host : hosts) {
                    System.out.println(host);
                }
            }

            System.out.println("-----------华丽的分割线----------");
        }


        // 3 关闭资源
        fs.close();
    }


    @Test
    public void testListStatus() throws IOException, InterruptedException, URISyntaxException {

        // 1 获取文件配置信息
        Configuration configuration = new Configuration();
        FileSystem fs = FileSystem.get(new URI("hdfs://mycluster"),
                configuration, "root");

        // 2 判断是文件还是文件夹
        FileStatus[] listStatus = fs.listStatus(new Path("/"));
        for (FileStatus fileStatus : listStatus) {

            // 如果是文件
            if (fileStatus.isFile()) {
                System.out.println("f:" + fileStatus.getPath().getName());
            } else {
                System.out.println("d:" + fileStatus.getPath().getName());
            }
        }

        // 3 关闭资源
        fs.close();
    }


    @Test
    public void putFileToHDFS() throws IOException, InterruptedException, URISyntaxException {

        // 1 获取文件系统
        Configuration configuration = new Configuration();
        FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:8020"), configuration, "root");

        // 2 创建输入流
        FileInputStream fis = new FileInputStream(new File("data/gsm.txt"));

        // 3 获取输出流
        FSDataOutputStream fos = fs.create(new Path("/gsm_io.txt"));

        // 4 流对拷
        IOUtils.copyBytes(fis, fos, configuration);

        // 5 关闭资源
        IOUtils.closeStream(fos);
        IOUtils.closeStream(fis);
        fs.close();
    }


    // 文件下载
    @Test
    public void getFileFromHDFS() throws IOException, InterruptedException, URISyntaxException {

        // 1 获取文件系统
        Configuration configuration = new Configuration();
        FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:8020"),
                configuration, "root");

        // 2 获取输入流
        FSDataInputStream fis = fs.open(new Path("/gsm_io.txt"));

        // 3 获取输出流
        FileOutputStream fos = new FileOutputStream(new File("data/gsm_io_copy.txt"));

        // 4 流的对拷
        IOUtils.copyBytes(fis, fos, configuration);

        // 5 关闭资源
        IOUtils.closeStream(fos);
        IOUtils.closeStream(fis);
        fs.close();
    }


    @Test
    public void readFileSeek2() throws IOException, InterruptedException, URISyntaxException {

        // 1 获取文件系统
        Configuration configuration = new Configuration();
        FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:8020"), configuration, "root");

        // 2 打开输入流,读取数据输出到控制台
        FSDataInputStream in = null;
        try {
            in = fs.open(new Path("/gsm.txt"));
            IOUtils.copyBytes(in, System.out, 4096, false);

            //从头再次读取
            in.seek(0);

            IOUtils.copyBytes(in, System.out, 4096, false);
        } finally {
            IOUtils.closeStream(in);
        }
    }

}
